<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */

namespace App\AdminApi\Api;

use App\AdminApi\AdminApiBasicsController;
use App\AdminApi\Module\Admin\Event\AdministerUser\AdministerUserLogin;
use App\AdminApi\Module\Admin\Service\MenuService;
use App\Common\Guard\AdminGuard;
use App\Sys;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Annotation\PostMapping;
use Psr\Http\Message\ResponseInterface;
use Zms\Attribute\Describe;
use Zms\HyperfResponse\Response;
use Zms\HyperfValidateAnnotations\Validate;
use Zms\Service\VerificationCode;

#[Controller(prefix: '/admin-api/login', server: self::SERVER)]
class LoginController extends AdminApiBasicsController
{
    #[
        Describe(title: '后台登录'),
        PostMapping('login'),
        Validate(
            rules: [
                ['account', 'required', 'error' => '请输入登录帐号'],
                ['password', 'required', 'error' => '请输入登录密码'],
                ['sign', 'required', 'error' => '请选获取验证码'],
                ['code', 'required', 'error' => '请输入验证码'],
            ]
        )
    ]
    public function login(VerificationCode $verification): ResponseInterface
    {
        $login_err = max((int)Sys::conf('admin.login_err', 0), 5); // 密码错误锁定次数
        $login_lock = max((int)Sys::conf('admin.login_lock', 0), 15); // 密码错误锁定时间

        $data = $this->request->getParsedBody();
        if ($verification->Verification($data['sign'], $data['code']) === false) {
            return Response::Api()->fail('验证码不正确');
        }
        /**
         * @var AdminGuard $user
         */
        $user = AdminGuard::where(['account' => $data['account']])->first();
        if (!$user) {
            return Response::Api()->fail('无效的账号');
        }

        // 检测锁定状态
        if ($user->locking > 0 && $user->locking > time()) {
            return Response::Api()->fail("您连续输入{$login_err}次密码错误,帐号已锁定,请" . date('Y-m-d H:i:s', $user->locking) . '后再试。');
        }

        // 验证密码
        if ($user->verifyPassword($data['password'], $user->password, $user->secret_key) === false) {
            ++$user->error; // 密码错误,锁定
            if ($user->error >= $login_err) {
                $user->locking = time() + $login_lock * 60;
            }
            $user->save();
            return Response::Api()->fail('账号或密码错误');
        }

        $userData = $user->userInfo();
        $userData['token'] = $this->guard()->login($user);

        Sys::event(new AdministerUserLogin($user->id)); // 触发登陆事件

        return Response::Api()->success(data: [
            'menu' => Sys::container(MenuService::class)->getAdministerMenu($user),
            'user' => $userData,
        ]);
    }

    #[
        Describe(title: '授权码登录'),
        PostMapping('code-login'),
        Validate(rules: [
            ['code', 'required', 'error' => '请输入授权码'],
        ])
    ]
    public function codeLogin(): ResponseInterface
    {
        $code = $this->request->input('code', '');
        $userId = Sys::cache()->get($code);
        if (!$userId) {
            return Response::Api()->fail('授权码已失效');
        }

        /**
         * @var AdminGuard $user
         */
        $user = AdminGuard::where(['id' => $userId])->first();
        if (!$user) {
            return Response::Api()->fail('无效的账号');
        }

        // 检测锁定状态
        if ($user->locking > 0 && $user->locking > time()) {
            return Response::Api()->fail('此账号当前已被锁定已锁定,请' . date('Y-m-d H:i:s', $user->locking) . '后再试。');
        }

        $userData = $user->userInfo();
        $userData['token'] = $this->guard()->login($user);

        Sys::event(new AdministerUserLogin($user->id, 'code')); // 触发登陆事件

        Sys::cache()->delete($code);

        return Response::Api()->success(data: [
            'menu' => Sys::container(MenuService::class)->getAdministerMenu($user),
            'user' => $userData,
        ]);
    }

    #[
        Describe(title: '获取登录验证码'),
        GetMapping('login-image-code'),
    ]
    public function loginImageCode(VerificationCode $verification): ResponseInterface
    {
        $verification = $verification->getImageVerificationCode(['width' => 100, 'height' => 35]);
        return Response::Api()->success('获取成功', $verification);
    }
}
